package com.own.business.system.user.business.service.impl;

import com.own.business.system.account.business.service.SystemAccountService;
import com.own.business.system.account.common.em.AccountType;
import com.own.business.system.user.business.core.SystemUserDeleteSpringHook;
import com.own.business.system.user.business.service.SystemUserInfoService;
import com.own.business.system.user.business.service.SystemUserSecurityService;
import com.own.business.system.user.business.service.SystemUserService;
import com.own.business.system.user.common.exception.SystemUserException;
import com.own.business.system.user.entity.bo.SystemUserBo;
import com.own.business.system.user.entity.map.SystemUserMapVo;
import com.own.business.system.user.entity.po.SystemUser;
import com.own.business.system.user.entity.po.SystemUserInfo;
import com.own.business.system.user.entity.po.SystemUserSecurity;
import com.own.business.system.user.entity.query.SystemUserQuery;
import com.own.business.system.user.entity.vo.SystemUserVo;
import com.own.business.system.user.mapper.SystemUserMapper;
import com.own.component.common.base.service.impl.AbstractBaseService;
import com.own.component.common.exception.BusinessException;
import com.own.component.common.model.UpdateModel;
import com.own.component.common.util.encrypt.EncryptUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;

/**
 * SystemUserServiceImpl
 *
 * @author chenxueli
 * @date 2021/06/24 15:46:54
 */
@Slf4j
@Service
public class SystemUserServiceImpl extends AbstractBaseService<
        SystemUser,
        SystemUserBo,
        SystemUserVo,
        SystemUserMapVo,
        SystemUserQuery,
        SystemUserMapper
        > implements SystemUserService {

    @Resource
    private SystemUserMapper systemUserMapper;

    @Resource
    private SystemUserInfoService systemUserInfoService;
    @Resource
    private SystemUserSecurityService systemUserSecurityService;

    @Resource
    private SystemAccountService systemAccountService;

    @Resource
    private SystemUserDeleteSpringHook systemUserDeleteSpringHook;

    /**
     * 添加信息
     *
     * @param bo 添加对象
     * @return 添加标识
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UpdateModel<SystemUserVo> add(SystemUserBo bo) {
        return super.add(bo);
    }

    /**
     * 修改信息
     *
     * @param pk 主键id
     * @param bo 修改对象
     * @return 修改标识
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UpdateModel<SystemUserVo> update(Long pk, SystemUserBo bo) {
        return super.update(pk, bo);
    }

    /**
     * 删除信息
     *
     * @param pk 主键id
     * @return 删除标识
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UpdateModel<Boolean> delete(Long pk) {
        return new UpdateModel<>().check(
                systemUserInfoService.delete(SystemUserInfo::getFkUserId, pk),
                systemUserSecurityService.delete(SystemUserSecurity::getFkUserId, pk),
                super.delete(pk)
        );
    }

    /**
     * 删除数据之前
     *
     * @param pk 删除数据的主键id
     * @return 处理后的po对象
     */
    @Override
    public Long beforeDelete(Long pk) {
        systemUserDeleteSpringHook.before(pk);
        return pk;
    }

    /**
     * 删除数据之后
     *
     * @param pk 删除数据的主键id
     * @return 处理后的vo对象
     */
    @Override
    public Boolean afterDelete(Long pk) {
        systemUserDeleteSpringHook.after(pk);
        return true;
    }

    /**
     * 处理账号禁用
     *
     * @param id 主键id
     * @return 是否修改成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UpdateModel<Boolean> disable(Long id) {
        var po = getPoById(id);
        po.setIsDisable((po.getIsDisable() + 1) % 2);
        return new UpdateModel<>(update(po).getFlag());
    }

    /**
     * 根据邮箱信息获取账号信息
     *
     * @param email 邮箱信息
     * @return 账号信息
     */
    @Override
    public SystemUser getUserByEmail(String email) {
        // 获取用户信息
        var info = systemUserInfoService.getByEmail(email);
        if (info == null) {
            return null;
        }
        return getPoById(info.getFkUserId());
    }

    /**
     * 根据手机号获取账号信息
     *
     * @param phone 手机号
     * @return 账号信息
     */
    @Override
    public SystemUser getUserByPhone(String phone) {
        // 获取用户信息
        var info = systemUserInfoService.getByPhone(phone);
        if (info == null) {
            return null;
        }
        return getPoById(info.getFkUserId());
    }

    /**
     * 根据用户名称获取账号信息
     *
     * @param userName 用户名称
     * @return 账号信息
     */
    @Override
    public SystemUser getUserByUserName(String userName) {
        // 获取用户信息
        var info = systemUserInfoService.getByName(userName);
        if (info == null) {
            return null;
        }
        return getPoById(info.getFkUserId());
    }

    /**
     * 修改密码
     *
     * @param userId      用户id
     * @param password    新密码
     * @param oldPassword 旧密码
     */
    @Override
    public void changePassword(Long userId, String password, String oldPassword) {
        if (StringUtils.isBlank(password)) {
            throw new BusinessException("密码为空");
        }
        // 查询对应的账号信息
        var po = systemAccountService.get(userId, AccountType.TEXT);
        if (po != null) {
            if (StringUtils.isNotBlank(oldPassword)) {
                if (!po.getPassword().equals(EncryptUtil.MD5.encrypt(oldPassword))) {
                    throw new SystemUserException("旧密码错误");
                }
            }
            systemAccountService.changePassword(po.getId(), password);
            return;
        }
        // 获取一个新的账号信息
        var userInfo = systemUserInfoService.getByUserId(userId);
        if (userInfo == null) {
            throw new SystemUserException("用户信息不存在");
        }
        var accountType = userInfo.getType();
        // 设置手机号为账号信息
        if (StringUtils.isNotBlank(userInfo.getPhone())) {
            var old = systemAccountService.get(userInfo.getPhone(), AccountType.TEXT, accountType);
            if (old == null) {
                systemAccountService.save(userInfo.getPhone(), password, AccountType.TEXT, accountType, userId);
                return;
            }
        }
        // 设置邮箱为账号信息
        if (StringUtils.isNotBlank(userInfo.getEmail())) {
            var old = systemAccountService.get(userInfo.getEmail(), AccountType.TEXT, accountType);
            if (old == null) {
                systemAccountService.save(userInfo.getEmail(), password, AccountType.TEXT, accountType, userId);
                return;
            }
        }
        // 设置userId为账号信息
        var old = systemAccountService.get(userId + "", AccountType.TEXT, accountType);
        if (old == null) {
            systemAccountService.save(userId + "", password, AccountType.TEXT, accountType, userId);
            return;
        }
        throw new SystemUserException("账号异常，请联系客服");
    }

    /**
     * 获取用户的注册天数
     *
     * @param userId 用户id
     * @return 注册天数
     */
    @Override
    public long registerDay(Long userId) {
        var po = getPoById(userId);
        return Duration.between(po.getGmtCreate(), LocalDateTime.now()).toDays() + 1;
    }

    /**
     * 获取用户的账号类型
     *
     * @param userId 用户id
     * @return 账号类型 1=普通账号 2=管理员
     */
    @Override
    public int getAccountTypeByUserId(Long userId) {
        return getPoById(userId).getType();
    }

}
